




#include "../inc/dllemvb.h"








/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: void COMMAND_SELECT(unsigned char *DFFileName,unsigned char DFFileNameLen,APDU_SEND *apdu_s)
º¯Êý¹¦ÄÜ: ¿¨ÎÄ¼þÑ¡ÔñÃüÁî
Èë¿Ú²ÎÊý: DFFileName-¿¨ÎÄ¼þÃû³Æ  DFFileNameLen-¿¨ÎÄ¼þ³¤¶È
          nextflag-ÊÇ·ñÓÐÏÂÒ»¸öÎÄ¼þ    apdu_s - ×éÖ¯µÄÒª·¢ËÍµÄAPDUÃüÁî
·µ »Ø Öµ: ÎÞ
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:         20140320
********************************************************************/
void EMVB_COMMAND_SELECT(unsigned char *DFFileName,unsigned char DFFileNameLen,unsigned char nextflag,APDU_SEND *apdu_s)
{
    if(nextflag)
    {
    	memcpy(apdu_s->Command,"\x00\xA4\x04\x02",4);
    }
	else
	{
    	memcpy(apdu_s->Command,"\x00\xA4\x04\x00",4);  
	}
	apdu_s->Lc = DFFileNameLen;
    memcpy(apdu_s->DataIn,DFFileName,DFFileNameLen);
	apdu_s->Le=256;
	apdu_s->EnableCancel = 1;       //Ê¹ÄÜ°´È¡Ïû¼ü

}




/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: void Emv_AppCopy(unsigned char i,unsigned char j,LISTAPPDATA *ListCandidate)
º¯Êý¹¦ÄÜ: Ó¦ÓÃÁÐ±í¿½±´
Èë¿Ú²ÎÊý: i,j
          ListCandidate - ´Ó¿¨ÖÐ¶Á³ö×éÖ¯µÄÓ¦ÓÃÁÐ±í
·µ »Ø Öµ: ÎÞ
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:         20140320
********************************************************************/
void Emv_AppCopy(unsigned char i,unsigned char j,LISTAPPDATA *ListCandidate)
{
	memcpy((unsigned char*)&ListCandidate[i],(unsigned char*)&ListCandidate[j],sizeof(LISTAPPDATA));
}


/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: unsigned char Emv_RebuildApplist(AppUnionStruct *App_UnionStruct)
º¯Êý¹¦ÄÜ: ÖØÐÂ½¨Á¢Ó¦ÓÃÁÐ±í
Èë¿Ú²ÎÊý: ÎÞ
·µ »Ø Öµ: ÎÞ
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:     20140320
********************************************************************/
unsigned char Emvb_RebuildApplist(EMVBAppUnionStruct *App_UnionStruct)  
{
	unsigned char i;
    
    LISTAPPDATA *tempapplist;
    
    
    tempapplist = App_UnionStruct->EMVTradeParam->AppListCandidate;
    
	
	if(App_UnionStruct->EMVTradeParam->AppListCandidatenum>1)
	{
		for(i=App_UnionStruct->EMVTradeParam->SelectedAppNo;i<App_UnionStruct->EMVTradeParam->AppListCandidatenum-1;i++)
			Emv_AppCopy(i,i+1,tempapplist);
		(App_UnionStruct->EMVTradeParam->AppListCandidatenum)--;
		return EMV_OK;
	}
	else 
	{
		return ERR_EMV_NoAppSel;
	}
	
}



//20140320
unsigned char Emvb_CommandReadECCashBalance(APDU_SEND *apdu_s)
{
	memcpy(apdu_s->Command,"\x80\xCA\x9F\x79",4);
	apdu_s->Lc=0;
	apdu_s->Le=256;
	apdu_s->EnableCancel = 1;
	
	return EMV_OK;
}


//20140408
unsigned char Emvb_ReadEcData(EMVBAppUnionStruct *tempApp_UnionStruct)
{
    APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	
    Emvb_CommandReadECCashBalance(&apdu_s);
    
    
	tempApp_UnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
    if(apdu_r.ReadCardDataOk != EMV_OK)
    {
    	return ERR_APP_TIMEOUT;
    }
    
	
    if(apdu_r.SWA==0x90 && apdu_r.SWB==0x00) 
	{
		if(!memcmp(apdu_r.DataOut,"\x9F\x79",2))// ECÓà¶î
		{
		    if(apdu_r.DataOut[2] != 6)  //sxl 10/10/19
		    {
		    	return ERR_EMV_IccCommand;
		    }
			dllemvb_avl_createsettagvalue((unsigned char *)TAG_VLPAvailableFund,&apdu_r.DataOut[3],6);
		}
	}
    return EMV_OK;
    
	
}



/*******************************************************************
×÷    Õß: sxl
º¯ÊýÃû³Æ: unsigned char CheckReadAFL(AppUnionStruct *tempApp_UnionStruct)
º¯Êý¹¦ÄÜ: ¶ÁAFL
Èë¿Ú²ÎÊý: ÎÞ
·µ »Ø Öµ: ÎÞ
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:         20140320
********************************************************************/
unsigned char EMVB_CheckReadAFL(EMVTAGCVLITEM *item)
{
    
	unsigned short t,i,j;
	unsigned char AFL_Num;
    unsigned char *AFL;


	AFL_Num = item->len>>2;
    if(AFL_Num == 0)
    {
		return ERR_EMV_IccDataFormat;
    }
	
	AFL = item->data;
    
    
	
	for(i = 0;i< AFL_Num;i++)
	{
	    j = i<<2;
		
		t=AFL[j];
		t>>=3;
		if(t==0||t>=31)
		{
			return ERR_EMV_IccDataFormat;
		}	
		if(AFL[j+1]<1)
		{
			return ERR_EMV_IccDataFormat;
		}
		if(AFL[j+2]<AFL[j+1])
		{
			return ERR_EMV_IccDataFormat;
		}
		if(AFL[j+3]>(AFL[j+2]-AFL[j+1]+1))
		{
			return ERR_EMV_IccDataFormat;	
		}
	}
	return EMV_OK;
}



//20140320
void Emvb_FormReadAflData(APDU_SEND *apdu_s,unsigned char tempAFL_RecordNum,unsigned char SFI)
{
	memcpy(apdu_s->Command,"\x00\xB2",2);
	apdu_s->Command[2]= tempAFL_RecordNum;  //record number 
	apdu_s->Command[3]= (SFI&0xF8)|0x04; //SFI
	apdu_s->Lc=0;
	apdu_s->Le=256;
    
	apdu_s->EnableCancel = 1;

}


//20140320
unsigned char Emvb_SendScriptCommand(unsigned char* Script,unsigned char ScriptLen,APDU_SEND *apdu_s)
{
	memcpy(apdu_s->Command,Script,4);
	memcpy(apdu_s->DataIn,(unsigned char*)&Script[5],Script[4]);
	apdu_s->Lc=Script[4];
	apdu_s->Le=0;//no Le
    
	apdu_s->EnableCancel = 0;
    
	return EMV_OK;
	
}


/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: unsigned char Emv_CommandIssuerAuthen(APDU_SEND *apdu_s,unsigned char *IssuAuthenData,unsigned char IssuAuthenDataLen)
º¯Êý¹¦ÄÜ: ·¢ËÍ·¢¿¨ÐÐÈÏÖ¤Êý¾Ý
Èë¿Ú²ÎÊý:
·µ »Ø Öµ:
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:  20140320
********************************************************************/
unsigned char Emvb_CommandIssuerAuthen(APDU_SEND *apdu_s,unsigned char *IssuAuthenData,unsigned char IssuAuthenDataLen)
{
	memcpy(apdu_s->Command,"\x00\x82\x00\x00",4);

	memcpy(apdu_s->DataIn,IssuAuthenData,IssuAuthenDataLen);
	apdu_s->Lc=IssuAuthenDataLen;
	apdu_s->Le=0;//no Le

	
	apdu_s->EnableCancel = 0;
	return EMV_OK;
	
}


/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: unsigned char Emv_CommandIssuerAuthen(APDU_SEND *apdu_s,unsigned char *IssuAuthenData,unsigned char IssuAuthenDataLen)
º¯Êý¹¦ÄÜ: ·¢ËÍ·¢¿¨ÐÐÈÏÖ¤Êý¾Ý
Èë¿Ú²ÎÊý:
·µ »Ø Öµ:
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:  20140320
********************************************************************/
unsigned char Emvb_IssuerAuthen(APDU_RESP *apdu_r)
{
	if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00)
	{ 
		return EMV_OK;
	}
	else
	{
		return ERR_EMV_IccReturn;
	}
			
	
}


/*******************************************************************
×÷    Õß: sxl
º¯ÊýÃû³Æ: unsigned char Paywave_ChooseApp(AppUnionStruct *App_UnionStruct)
º¯Êý¹¦ÄÜ: Ñ¡ÔñAPP
Èë¿Ú²ÎÊý:
·µ »Ø Öµ:
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:         20140320
********************************************************************/
unsigned char contactless_ChooseApp(EMVBAppUnionStruct *tempApp_UnionStruct)
{	
	unsigned char i,j,temp; //bPriority,bConfirm,
	unsigned char *tempselectappno;
	unsigned char *tempappnum;

	unsigned char noprioritynum = 0;
	unsigned char tmpseq[16];
	unsigned char tmpapprtiority[16];
	unsigned char AppPriority[16];
    unsigned char AppSeq[16];
	
	
	LISTAPPDATA *tempAppAppData;
	
    tempselectappno = &(tempApp_UnionStruct->EMVTradeParam->SelectedAppNo);
	tempappnum = &(tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum);
    tempAppAppData = tempApp_UnionStruct->EMVTradeParam->AppListCandidate;
	
    
    if(*tempappnum<1)      //Ã»ÓÐºÍÖÕ¶ËÁÐ±íÆ¥ÅäµÄ±êÇ©
	{
		return ERR_EMV_NoAppSel;
	}

	
	*tempselectappno = 0xff;
		
	
	if(*tempselectappno>*tempappnum)
	{
		//bPriority=1;
		//bConfirm=1;
		for(i=0;i<*tempappnum;i++)
		{
			AppPriority[i]=(tempAppAppData+i)->Priority & 0x0F;
			AppSeq[i]=i;
		}
		if(*tempappnum==1)
		{		
		    *tempselectappno = 0;
		}
		else
		{
			for(j=0;j<*tempappnum-1;j++)
			{
				for(i=0;i<*tempappnum-1-j;i++)
				{
					if(AppPriority[i]>AppPriority[i+1])
					{
						temp=AppPriority[i];
						AppPriority[i]=AppPriority[i+1];
						AppPriority[i+1]=temp;
						temp=AppSeq[i];
						AppSeq[i]=AppSeq[i+1];
						AppSeq[i+1]=temp;
					}
				}
			}
			noprioritynum = 0;
			for(i=0;i<*tempappnum;i++)
			{
				if(AppPriority[i]==0) noprioritynum++;
			}
			if(noprioritynum)  //have no priority app
			{
				memcpy(tmpapprtiority,&AppPriority[noprioritynum],*tempappnum - noprioritynum);
				memcpy(&tmpapprtiority[*tempappnum - noprioritynum],AppPriority,noprioritynum);
				memcpy(AppPriority,tmpapprtiority,*tempappnum);

				memcpy(tmpseq,&AppSeq[noprioritynum],*tempappnum - noprioritynum);
				memcpy(&tmpseq[*tempappnum - noprioritynum],AppSeq,noprioritynum);
				memcpy(AppSeq,tmpseq,*tempappnum);
				
			}
            
			*tempselectappno = AppSeq[0];
			
		}
	}



	if(*tempselectappno>*tempappnum)
	{
	    return ERR_EMV_CancelTrans;
	}

	return EMV_OK;


}


//20140320
unsigned char contactless_checkifRedundantData(unsigned char *tag,unsigned char *rundatabuf,unsigned int rundatalen)
{
	unsigned int index = 0;
	unsigned char temptag[4],temptaglen;
	EMVTAGCVLITEM tempemvtagitem;

	while(index < rundatalen)
	{
		temptaglen = 0;
        
		temptag[temptaglen++] = rundatabuf[index];
        if((temptag[0]&0x1f) == 0x1f)
        {
        	temptag[temptaglen++] = rundatabuf[index+1];
			if(tag[1]&0x80)
			{
				temptag[temptaglen++] = rundatabuf[index+2];
			}
        }
        
        if(memcmp(tag,temptag,temptaglen) == 0)
        {
            if(EMVB_TagBaseLib_read(temptag,temptaglen,TAGTYPE_PAYWAVE|TAGTYPE_EMV,&tempemvtagitem) == 0)
            {
        		return 1;
            }
			else
			{
				return 0;
			}
        }
        
		index += temptaglen;
		
	}

	return 0;
}



const char SM_IDm[] = "31323334353637383132333435363738";
extern int  GetSummary (const char *pPkeyX, const char *pPkeyY,const char *pSrcData, unsigned short pSrcDataLen,const char *pIDA, unsigned char *pSummary);
extern void *emvblib_malloc (size_t size);

unsigned char Emvb_SM_SignatureVerf(EMVBAppUnionStruct *tempApp_UnionStruct,unsigned char* dgtsgnt, unsigned char* Datatbsign, unsigned short DatatbsignLen, unsigned char *pkdata, unsigned short pkdatalen)
{
	unsigned char *PKdataASC,PKdataX[128], PKdataY[128];  //[256]
	unsigned char *signdataASC,signR[128], signS[128];   //[256]
	//unsigned char *data2bsignASC;       //[3072]  2048¸ö×Ö½ÚµÄ´¦Àí
	unsigned short tmplen;
	//unsigned char pDstBuf[128] = {0};
	//int nLen;
    //unsigned char *sendverifydata;
	//int sendverifydatalen;
	//unsigned char retCode;
    
	
    
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SM_SignatureVerf1\r\n");
	#endif
	
    
	PKdataASC = (unsigned char *)emvblib_malloc(256);
	memset(PKdataASC,0,256);
	memset(PKdataX,0,sizeof(PKdataX));
	memset(PKdataY,0,sizeof(PKdataY));
	signdataASC = (unsigned char *)emvblib_malloc(256);
	memset(signdataASC,0,256);
	memset(signR,0,sizeof(signR));
	memset(signS,0,sizeof(signS));
    
	
	//memcpy(pkdata,"\x0A\xE4\xC7\x79\x8A\xA0\xF1\x19\x47\x1B\xEE\x11\x82\x5B\xE4\x62\x02\xBB\x79\xE2\xA5\x84\x44\x95\xE9\x7C\x04\xFF\x4D\xF2\x54\x8A\x7C\x02\x40\xF8\x8F\x1C\xD4\xE1\x63\x52\xA7\x3C\x17\xB7\xF1\x6F\x07\x35\x3E\x53\xA1\x76\xD6\x84\xA9\xFE\x0C\x6B\xB7\x98\xE8\x57",64);
    
	EMVBcdToAsc(PKdataASC,pkdata,pkdatalen);
	tmplen = pkdatalen;
	memcpy(PKdataX, PKdataASC, tmplen);
	PKdataX[tmplen] = '\0'; 
	memcpy(PKdataY, (unsigned char *)&PKdataASC[tmplen], tmplen);
	PKdataY[tmplen] = '\0'; 
    
	emvblib_free(PKdataASC);
    
	tmplen = 64;          //Êý×ÖÇ©Ãû³¤¶È£¬Îª64
    //memcpy(dgtsgnt,"\x40\xF1\xEC\x59\xF7\x93\xD9\xF4\x9E\x09\xDC\xEF\x49\x13\x0D\x41\x94\xF7\x9F\xB1\xEE\xD2\xCA\xA5\x5B\xAC\xDB\x49\xC4\xE7\x55\xD1\x6F\xC6\xDA\xC3\x2C\x5D\x5C\xF1\x0C\x77\xDF\xB2\x0F\x7C\x2E\xB6\x67\xA4\x57\x87\x2F\xB0\x9E\xC5\x63\x27\xA6\x7E\xC7\xDE\xEB\xE7",64);
    
	EMVBcdToAsc(signdataASC,dgtsgnt,tmplen);
	memcpy(signR, signdataASC,tmplen);
	signR[tmplen] = '\0';
	memcpy(signS, (unsigned char *)&signdataASC[tmplen], tmplen);
	signS[tmplen] = '\0'; 
    
	emvblib_free(signdataASC);
    
    
    
    //memcpy(Datatbsign,"message digest",14);
	//DatatbsignLen = 14;
	
	//data2bsignASC = (unsigned char *)emvblib_malloc((DatatbsignLen<<1)+100);
    //memset(data2bsignASC,0,(DatatbsignLen<<1)+100);
	
	//EMVBcdToAsc(data2bsignASC,Datatbsign,DatatbsignLen);
	//data2bsignASC[DatatbsignLen<<1] = '\0';
    
	
	#ifdef EMVB_DEBUG
	emvb_printf("\r\n Datatbsign: \r\n");
	emvb_printf("\r\n DatatbsignLen = %d \r\n ",DatatbsignLen);
 	EmvPrintFormat(Datatbsign, DatatbsignLen);
	#endif
	
	#ifdef EMVB_DEBUG
	emvb_printf("\r\n PKdataX: \r\n");
	EmvPrintFormat(PKdataX, pkdatalen);
	emvb_printf("\r\n PKdataY: \r\n");
	EmvPrintFormat(PKdataY, pkdatalen);
	emvb_printf("\r\n signR: \r\n");
	EmvPrintFormat(signR, 64);
	emvb_printf("\r\n signS: \r\n");
	EmvPrintFormat(signS, 64);
	//printfemv("\r\n data2bsignASC: \r\n");
	//EmvPrintFormat(data2bsignASC, DatatbsignLen*2);
	#endif

	return EMV_ERR;

	#if 0
    //#if 0   //sxl?
    //nLen = GetSummary((char *)&PKdataX, (char *)&PKdataY,(char *)&Datatbsign[0],DatatbsignLen,SM_IDm, pDstBuf); 
	if (nLen == 0 || nLen > 32)
	{
		return ERR_EMV_IccDataFormat;
	}
    //#endif
	
    sendverifydata = emvblib_malloc(512);
	memset(sendverifydata,0,512);
    
	sendverifydatalen = 0;
    sendverifydata[sendverifydatalen++] = pkdatalen;
	memcpy(&sendverifydata[sendverifydatalen],pkdata,pkdatalen);
	sendverifydatalen += pkdatalen;
    
	sendverifydata[sendverifydatalen++] = 64;
	memcpy(&sendverifydata[sendverifydatalen],dgtsgnt,64);
	sendverifydatalen += 64;
    
	sendverifydata[sendverifydatalen++] = nLen;
	memcpy(&sendverifydata[sendverifydatalen],pDstBuf,nLen);
	sendverifydatalen += nLen;
    
    
	//sxl  Õâ¸öº¯Êý»¹Ã»ÓÐ¸ÄÐ´Íê  ²âÊÔ
    retCode = tempApp_UnionStruct->sendverifysmmac(sendverifydata,sendverifydatalen);  //test
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SM_SignatureVerf retCode = %d\r\n",retCode);
	#endif
	if(retCode != 0)
	{
	    emvblib_free(sendverifydata);
		return ERR_EMV_IccDataFormat;
	}
	#ifdef EMVB_DEBUG
   	emvb_printf("\r\n×ß³öSM_SignatureVerf\r\n");
	#endif
    
    
   	emvblib_free(sendverifydata);
	return EMV_OK;
	#endif
	
	
}


unsigned char Emvb_GetTag(unsigned char *DOL,unsigned short index,unsigned char *tag)
{
	unsigned char taglen;

	
	memset(tag,0,4);
	taglen = 0;
	tag[taglen++] = DOL[index];
	if((tag[0]&0x1f) == 0x1f)
	{
		tag[taglen++] = DOL[index+1];
		if(tag[1]&0x80)
		{
			tag[taglen++] = DOL[index+2];
		}
	}

	return taglen;
}



unsigned char Emvb_DataDiscard(unsigned char *DataOut,unsigned short *index)
{
    unsigned char k;
	unsigned short len;
	unsigned short tempindex;
    
	tempindex = *index;
	k=DataOut[tempindex];
	if((k&0x1F)==0x1F)
		tempindex++;
	tempindex++;
	if(ParseExtLen(DataOut,&tempindex,&len))
	{
		return ERR_EMV_IccDataFormat;
	}
	tempindex+=len;

	*index = tempindex;

	return EMV_OK;
	
}


unsigned char Emvb_DOLDataPack(unsigned char *tag,unsigned char taglen,unsigned short *tagindex,unsigned char *DOL,unsigned char *DOLData,unsigned short *dataoutindex)
{
    
	EMVTAGCVLITEM *DOLdataitem;
    unsigned short templen;
	unsigned short k,m;
	unsigned short index,indexOut;
	unsigned char buf[300];
	unsigned char bInTable = 0;

	index = *tagindex;
	indexOut = *dataoutindex;
	
	DOLdataitem = dllemvb_avl_gettagitempointer(tag);
	memset(buf,0,sizeof(buf));
	if(DOLdataitem != NULL)
	{
		index += taglen;
		
		if(ParseExtLen(DOL,&index,&templen))
		{
			return ERR_EMV_IccDataFormat;
		}
		
		
		k = templen;   // 1
		m=DOLdataitem->len; // 4

		
		if(DOLdataitem->datafomat&TAGFORMAT_N)//numeric
		{
			if(k>=m)
			{
				if(m)
				{
					memcpy(&buf[k-m],DOLdataitem->data,m);
				}
				memcpy(&DOLData[indexOut],buf,k);
			}
			else
			{
				if(m)
				{
					memcpy(buf,DOLdataitem->data,m);
				}
				memcpy(&DOLData[indexOut],&buf[m-k],k);
			}
		}
		else if(DOLdataitem->datafomat&TAGFORMAT_CN)//compact numeric
		{
			if(m)
			{
				memset(buf,0xFF,255);
				memcpy(buf,DOLdataitem->data,m);
				memcpy(&DOLData[indexOut],buf,k);
			}
			else
			{
				memset(buf,0x00,255);
				memcpy(&DOLData[indexOut],buf,k);
			}
		}
		else//other formats
		{
			if(m)
			{
				memcpy(buf,DOLdataitem->data,m);
			}
			memcpy(&DOLData[indexOut],buf,k);
		}


		indexOut+=k;
		bInTable=1;
	}
	
	if(!bInTable)
	{
		index += taglen;
		if(ParseExtLen(DOL,&index,&templen))
		{
			return ERR_EMV_IccDataFormat;
		}
		k = templen;
		memcpy(&DOLData[indexOut],buf,k);
		indexOut+=k;
	}
	
	*tagindex = index;
	*dataoutindex = indexOut;
	
	return EMV_OK;

	
}


unsigned char Emvb_AFLCheckSDAandCVM(EMVBAppUnionStruct *tempApp_UnionStruct)
{
    EMVTAGCVLITEM *item;
	unsigned char temp[2];
	
	item = dllemvb_avl_gettagitempointer((unsigned char *)TAG_SDATagList);
	if(item != NULL) //if SDA_TL exist
	{
	    if(item->len)
	    {
	        tempApp_UnionStruct->EMVTradeParam->bErrSDATL = 1;
		    if(item->len == 1)
		    {
		    	if(item->data[0]==0x82)
		    	{
	                
					if(dllemvb_avl_gettagvalue_spec((unsigned char *)TAG_AIP,temp,0,2))
					{
						#ifdef EMVB_DEBUG
			            emvb_printf("tempiccdatatable err12345 \r\n");
			            #endif
						
						return ERR_EMV_IccDataFormat;
					}
		    		memcpy((unsigned char*)&tempApp_UnionStruct->EMVTradeParam->AuthData[tempApp_UnionStruct->EMVTradeParam->AuthDataLen],temp,2);
					tempApp_UnionStruct->EMVTradeParam->AuthDataLen += 2;
					tempApp_UnionStruct->EMVTradeParam->bErrSDATL = 0;
		    	}
		    }
	    }
	}


	//CVM list exist
	item = dllemvb_avl_gettagitempointer((unsigned char *)TAG_CVMList);
	if(item != NULL)
	{
	    if(item->len%2 != 0)
	    {
	    	return ERR_EMV_IccDataFormat;
	    }
	}

	return EMV_OK;
}



/*******************************************************************
×÷    Õß:
º¯ÊýÃû³Æ: unsigned char Emv_CheckDateFormat(unsigned char * date)
º¯Êý¹¦ÄÜ: ÅÐ¶ÏÈÕÆÚ¸ñÊ½ÊÇ·ñ·Ç·¨
Èë¿Ú²ÎÊý: 1ÈÕÆÚ
·µ »Ø Öµ: OKºÏ·¨.ERR·Ç·¨
Ïà¹Øµ÷ÓÃ:
±¸    ×¢:
ÐÞ¸ÄÐÅÏ¢:         20130731    //sxl?2022要修改完善
********************************************************************/
unsigned char Emv_CheckDateFormat(unsigned char * date)
{
    unsigned char i,k,yymmdd[4+1];
    unsigned char isLeapYear = 0;
    int  nYear      = 0;

    for(i=0;i<4;i++)
    {
        k=date[i];
        if((k&0x0F) > 9) return EMV_ERR;
        if(((k&0xF0)>>4) > 9) return EMV_ERR;
        yymmdd[i]=((k&0xF0)>>4)*10 + (k&0x0F);
    }
    #ifdef EMVB_DEBUG
    emvb_printf("\r\n yymmdd[i] = %x,%x,%x,%x", yymmdd[0], yymmdd[1], yymmdd[2], yymmdd[3]);
    #endif
    // check year
    nYear = yymmdd[0] * 100 + yymmdd[1];
    if((nYear % 4 == 0 && nYear % 100 != 0) || (nYear % 400 == 0) )
    {
        isLeapYear = 1;
    }
    #ifdef EMVB_DEBUG
    emvb_printf("\r\n nYear = %d, isLeapYear = %d",nYear, isLeapYear );
    #endif
    // check month
    if(yymmdd[2]<1 || yymmdd[2]>12) return EMV_ERR; //1 <= month <=12

    // check day
    switch(yymmdd[2])
    {
        case 0x01:
        case 0x03:
        case 0x05:
        case 0x07:
        case 0x08:
        case 0x0A:
        case 0x0C: // 31 days
            if(yymmdd[3]<1 || yymmdd[3]>31) return EMV_ERR; //1 <= date    <= 31
            break;
        case 0x02:
            if(isLeapYear) // Leap year, 29 days
            {
                if(yymmdd[3]>29) return EMV_ERR;
            }
            else          // none Leap year, 28 days
            {
                if(yymmdd[3]>28) return EMV_ERR;
            }
            break;
        default:
            if(yymmdd[3]<1 || yymmdd[3]>30) return EMV_ERR; //1 <= date    <= 30
            break;
    }


    return EMV_OK;

}


void EmvPrintFormat(unsigned char *src, unsigned short Len)
{ 
	unsigned short i = 0;

	emvb_printf("\r\n%04X: ", 0);
	for (i = 0; i < Len; i++)
	{
		if (i != 0 && i % 16 == 0)
		{
			emvb_printf("\r\n%04X: ",i);
		}	
		emvb_printf("%02X ", src[i]);
	}
	emvb_printf("\r\n");	
}


#define EMVBLIB_VERSION "emvlib1.01"
void Emvb_get_getver(char *emvlibversion)
{

    strcpy(emvlibversion, EMVBLIB_VERSION);
}
